//
// Created by sai on 2019/2/27.
//
#include "DoublyLinkedList.h"

bool IsLast(Position pos, DoublyList list) {
    return pos->next == NULL;
}

bool IsFirst(Position pos, DoublyList list) {
    return pos->prev == NULL;
}

bool IsEmpty(DoublyList list) {
    return list->FirstNode == NULL && list->LastNode == NULL;
}

DoublyList MakeEmpty(DoublyList list) {
    list = malloc(sizeof(struct List));
    list->FirstNode = NULL;
    list->LastNode = NULL;
    list->Len = 0;
    return list;
}

Position Find(ElementType elem, DoublyList list) {
    Position node;
    node = list->FirstNode;
    while (node != NULL && node->date != elem)
        node = node->next;
    return node;
}

Position FindPrevious(ElementType elem, DoublyList list) {
    Position node;
    node = Find(elem, list);
    return node->prev;
}

void DeletePosition(ElementType elem, DoublyList list) {
    Position node, NextNode;
    node = FindPrevious(elem, list);
    NextNode = node->next;
    node->next = NextNode->next;
    NextNode->next->prev = node;
    free(NextNode);
}

void DeleteNode(ElementType elem, DoublyList list) {
    Position node;
    node = Find(elem, list);
    assert(node);
    if (IsFirst(node, list)) {
        list->FirstNode = node->next;
        node->next->prev = NULL;
        free(node);
    } else if (IsLast(node, list)) {
        list->LastNode = node->prev;
        node->prev->next = NULL;
        free(node);
    } else
        DeletePosition(elem, list);
    list->Len = list->Len - 1;
}

void InsertPosition(ElementType elem, DoublyList list, Position pos) {
    Position TmpNode;
    TmpNode = malloc(sizeof(struct Node));
    assert(TmpNode);
    TmpNode->date = elem;
    TmpNode->prev = pos;
    TmpNode->next = pos->next;
    pos->next->prev = TmpNode;
    pos->next = TmpNode;
}

void InsertNode(ElementType elem, DoublyList list, Position pos) {
    Position node;
    if (IsEmpty(list)) {
        node = malloc(sizeof(struct Node));
        list->FirstNode = node;
        list->LastNode = node;
        node->date = elem;
        node->prev = NULL;
        node->next = NULL;
    } else if (IsLast(pos, list)) {
        node = malloc(sizeof(struct Node));
        node->date = elem;
        node->prev = pos;
        node->next = NULL;
        pos->next = node;
        list->LastNode = node;
    } else
        InsertPosition(elem, list, pos);
    list->Len = list->Len + 1;
}

void DeleteDoublyList(DoublyList list) {
    Position node, TmpNode;
    node = list->FirstNode;
    while (node != NULL) {
        TmpNode = node->next;
        free(node);
        node = TmpNode;
    }
    free(list);
}

void Append(DoublyList list, ElementType elem) {
    InsertNode(elem, list, list->LastNode);
}

void Print_DoublyList(DoublyList list) {
    Position pos;
    if (IsEmpty(list)) {
        puts("DoublyList is empty");
        return;
    }
    pos = list->FirstNode;
    while (pos != NULL) {
        printf("%d ", pos->date);
        pos = pos->next;
    }
}